#pragma once
#include <iostream>
namespace NBE
{
	typedef unsigned long long clocks;

	class Time
	{
	private:
		double desireFramePerSecond;
		double desireSecondsPerFrame;
		clocks desireClocksPerFrame;

	public:
		Time::Time(const double frameRate = 60 ):desireFramePerSecond(frameRate),
			desireSecondsPerFrame(1.0/desireFramePerSecond),
			desireClocksPerFrame(secondsToClocks(desireSecondsPerFrame))
		{}
		inline clocks Time::GetSystemClocks()
		{
			LARGE_INTEGER time;
			QueryPerformanceCounter(&time);
			return time.QuadPart;
		}
		inline clocks Time::GetClockFrequency()
		{
			static LARGE_INTEGER frequency = {0};
			if ( frequency.QuadPart == 0)
			{
				QueryPerformanceFrequency(&frequency);
			}
			return frequency.QuadPart;
		}
		inline double Time::GetClockFrequencyDouble()
		{
			return static_cast<double>(GetClockFrequency());
		}
		inline double Time::clocktoSeconds(clocks c)
		{
			return c / GetClockFrequencyDouble();
		}
		inline clocks Time::secondsToClocks(double seconds)
		{
			return static_cast<clocks>(seconds * GetClockFrequencyDouble());
		}
		inline double Time::getsystemTimeSeconds()
		{
			return clocktoSeconds(GetSystemClocks());	
		}
		inline clocks Time::PreciseWaitUntill(clocks stopWaitTime)
		{
			//TODO use sleep to make this less expensive for cases where the delay is > 16ms
			clocks now;
			while((now = GetSystemClocks()) < stopWaitTime );
			return now;
		}

		inline void Time::resetFPSLimit(const double frameRate)
		{
			desireFramePerSecond = frameRate;
			desireSecondsPerFrame = 1.0/desireFramePerSecond;
			desireClocksPerFrame = secondsToClocks(desireSecondsPerFrame);
		}

		inline clocks Time::getDesireColocsPerFrame()
		{
			return desireClocksPerFrame;
		}
	};


}
